Conversation
Mirko-von-Leipzig
left a comment
There was a problem hiding this comment.
Minor nits, but I think we need to allow for a single block fork.
| /// block commitment). | ||
| /// | ||
| /// On success, returns the signature and the new block header (which becomes the new chain tip). | ||
| #[instrument(target = COMPONENT, skip_all, err, fields(chain_tip = chain_tip.block_num().as_u32()))] |
There was a problem hiding this comment.
We should also log block.number and block.commitment
There was a problem hiding this comment.
those aren't available from ProposedBlock, if thats what you mean. I could add an event in the fn? After
let (proposed_header, _) = proposed_blockThere was a problem hiding this comment.
Avoid events, but we can inject the value within the function using span.set_attribute
8586d1d to
e2dee35
Compare
| #[error("conflict: {0}")] | ||
| Conflict(String), |
There was a problem hiding this comment.
This feels a bit weird - should we not have more specific variants?
| CREATE INDEX idx_validated_transactions_block_num ON validated_transactions(block_num); | ||
|
|
||
| CREATE TABLE block_headers ( | ||
| block_num INTEGER PRIMARY KEY, |
There was a problem hiding this comment.
If we also store block_commitment can we avoid pulling in the entire header each check?
There was a problem hiding this comment.
I think this breaks under concurrent requests. This is compounded by having separate database transactions/queries instead of using a single transaction throughout.
I'm unsure if using a single database tx would help either, since its possible to concurrently perform an upsert on block N, while storing N+1 based on the old value.
A simple fix is adding a Semaphor with exactly one permit after deserialization. I still don't like that we keep opening new database transactions multiple times per request though. This is also a problem in the store, but that's a diesel problem.
Context
Closes #1773.
In #1764 we are adding a validator subcommand to construct and sign the genesis block. In this PR, we are building on top of that and storing the genesis block as the initial chain tip in the validator DB.
The validator is updated to maintain a chain tip as it continues to sign blocks. It uses this state to validate chain continuity (block number sequence, commitment references, etc).
Changes
block_headerstable to the validator database.--data-directoryargument).validate_blocknow enforces chain continuity: sequential block numbers and matching previous block commitments.validate_blockallows for the current chain tip inblock_headerstable to be overwritten to allow for idempotence.dbmodule public so the bootstrap command can callsave_chain_tipandloaddirectly.